package com.example.service;

import cn.hutool.core.util.StrUtil;
import com.example.entity.GeneratorConfig;
import com.example.entity.PickupCode;
import com.example.exception.CustomerException;
import com.example.mapper.GeneratorConfigMapper;
import com.example.mapper.PackageMapper;
import com.example.mapper.PickupCodeMapper;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.nio.file.Paths;
import java.util.Date;

@Service
public class GeneratorService {
    private static final Long CONFIG_ID = 1L;

    @Resource
    private GeneratorConfigMapper generatorConfigMapper;

    @Resource
    private PickupCodeMapper pickupCodeMapper;

    @Resource
    private PackageMapper packageMapper;

    @PostConstruct
    public void initConfig() {
        GeneratorConfig config = generatorConfigMapper.selectById(CONFIG_ID);
        if (config == null) {
            throw new CustomerException("生成器配置未初始化");
        }

        // 查询当前最新的取件码记录
        PickupCode latestCode = pickupCodeMapper.selectLatestCode();
        if (latestCode != null) {
            // 更新配置至最新状态
            config.setCurrentShelf(latestCode.getShelf());
            config.setCurrentLayer(latestCode.getLayer());
            config.setCurrentSequence(latestCode.getSequence());
            generatorConfigMapper.updateConfig(config);
        }
    }

    @Transactional
    public String generatePickupCode(String trackingNumber) {
        // 优先查询可回收的取件码（trackingNumber 为空）
        PickupCode recycledCode = pickupCodeMapper.selectRecycledCode();
        if (recycledCode != null) {
            // 更新取件码的 trackingNumber 为当前包裹单号
            pickupCodeMapper.assignTrackingNumber(recycledCode.getId(), trackingNumber);
            // 同步到 package 表
            String pickupCodeStr = String.format("%d-%d-%d",
                    recycledCode.getShelf(),
                    recycledCode.getLayer(),
                    recycledCode.getSequence());
            packageMapper.updatePickupCodeByTrackingNumber(trackingNumber, pickupCodeStr);
            return pickupCodeStr;
        }

        // 检查 package 表是否已有取件码
        String existingCode = packageMapper.selectPickupCodeByTrackingNumber(trackingNumber);
        if (StrUtil.isNotBlank(existingCode)) {
            return existingCode; // 直接返回已存在的取件码
        }

        // 检查 pickup_code 表是否存在记录
        int codeCount = pickupCodeMapper.countByTrackingNumber(trackingNumber);
        if (codeCount > 0) {
            // 如果存在，从 pickup_code 表获取最新取件码并同步到 package 表
            PickupCode latestCode = pickupCodeMapper.selectLatestByTrackingNumber(trackingNumber);
            String pickupCodeStr = String.format("%d-%d-%d", latestCode.getShelf(), latestCode.getLayer(), latestCode.getSequence());
            packageMapper.updatePickupCodeByTrackingNumber(trackingNumber, pickupCodeStr);
            return pickupCodeStr;
        }

        GeneratorConfig config;
        int retryCount = 0;
        boolean updated;

        int currentShelf;
        int currentLayer;
        int currentSequence;
        do {
            config = generatorConfigMapper.selectById(CONFIG_ID);
            if (config == null) {
                throw new CustomerException("生成器配置未初始化");
            }

            currentShelf = config.getCurrentShelf();
            currentLayer = config.getCurrentLayer();
            currentSequence = config.getCurrentSequence();

            // 递增逻辑
            currentSequence++;
            if (currentSequence > 10) {
                currentSequence = 1;
                currentLayer++;
                if (currentLayer > 5) {
                    currentLayer = 1;
                    currentShelf++;
                }
            }

            GeneratorConfig newConfig = new GeneratorConfig();
            newConfig.setId(CONFIG_ID);
            newConfig.setCurrentShelf(currentShelf);
            newConfig.setCurrentLayer(currentLayer);
            newConfig.setCurrentSequence(currentSequence); // 更新为递增后的值
            newConfig.setVersion(config.getVersion());

            updated = generatorConfigMapper.updateConfig(newConfig) > 0;
            retryCount++;
        } while (!updated && retryCount < 5);

        if (!updated) {
            throw new CustomerException("生成取件码失败，请重试");
        }

        PickupCode code = new PickupCode();
        code.setTrackingNumber(trackingNumber);
        code.setShelf(currentShelf);    // 使用递增后的值
        code.setLayer(currentLayer);
        code.setSequence(currentSequence);
        code.setCreatedAt(new Date());
        pickupCodeMapper.insert(code);

        String pickupCode = String.format("%d-%d-%d", currentShelf, currentLayer, currentSequence);

        // 更新 package 表的 pickupCode 字段
        packageMapper.updatePickupCodeByTrackingNumber(trackingNumber, pickupCode);

        return pickupCode;
    }

    @Transactional
    public void recyclePickupCode(String trackingNumber) {
        // 将 pickup_code 表中对应 trackingNumber 置空
        pickupCodeMapper.clearTrackingNumber(trackingNumber);
    }

    public String generateQRCode(String trackingNumber) throws Exception {
        if (StrUtil.isBlank(trackingNumber)) {
            throw new CustomerException("快递单号不能为空");
        }

        // 生成二维码配置
        int width = 300;
        int height = 300;
        String format = "png";
        String content = trackingNumber; // 二维码包含的信息

        // 使用ZXing生成二维码
        String basePath = System.getProperty("user.dir") + "/files/qr_code/"; // 项目根目录下
        String fileName = trackingNumber + ".png";
        String fullPath = basePath + fileName;

        // 创建目录
        File dir = new File(basePath);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        // 保存文件
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height);
        MatrixToImageWriter.writeToPath(bitMatrix, format, Paths.get(fullPath));

        return "/files/qr_code/" + fileName; // 返回访问路径
    }
}
